package org.noip.amdg;

import java.awt.Font;
import java.awt.Graphics;
import java.awt.font.TextAttribute;
import java.text.AttributedString;
import java.util.List;
import java.util.SortedMap;

import javax.swing.JPanel;

import org.noip.amdg.GameModel.GameMode;

public class GamePane extends JPanel {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	private static final int WIDTH = 150;
	private static final int START_HEIGHT = 130;
	private static final int GAP = 10;
	private static final int TOTAL_HEIGHT = 400;
	
	private final GameModel gameModel;

	private final AttributedString gameOver = new AttributedString("Game Over!");
	private final AttributedString pause = new AttributedString("Pause!");
	
	private volatile Animation currentAnimation;

	public GamePane(final GameModel gameModel) {
		this.gameModel = gameModel;
		Font font = new Font("Sans", Font.BOLD, 28);
		gameOver.addAttribute(TextAttribute.FONT, font);
		pause.addAttribute(TextAttribute.FONT, font);
		setDoubleBuffered(true);
	}

	@Override
	public void paint(Graphics graphics) {
		super.paint(graphics);
		
		final List<Bucket> buckets = gameModel.getBuckets();
		
		final int score = gameModel.getScore();
		final int level = gameModel.getLevel();
		final String answer = gameModel.getCurrentAnswer();
		final int numberOfBuckets = buckets.size();

		// Draw Stats
		graphics.drawString("Score: " + score, numberOfBuckets * (WIDTH + GAP)
				, GAP * 2);
		
		graphics.drawString("Level: " + level, numberOfBuckets * (WIDTH + GAP)
				, GAP * 4);
		
		graphics.drawString(answer, numberOfBuckets * (WIDTH + GAP)
				, GAP * 6);

		
		// Draw funnel:
		final int funnel = gameModel.getFunnelPosition() / GameModel.getBucketSteps();
		final int offset = (int) (((double)gameModel.getFunnelPosition() / GameModel.getBucketSteps() - funnel) * (WIDTH + GAP));
		
		graphics.drawLine(funnel * (WIDTH + GAP) + offset, GAP, funnel * (WIDTH + GAP) + GAP + offset, GAP);
		graphics.drawLine(funnel * (WIDTH + GAP) + GAP + offset, GAP, funnel * (WIDTH + GAP) + WIDTH / 2 - GAP + offset, GAP * 3);
		graphics.drawLine(funnel * (WIDTH + GAP) + WIDTH / 2 + GAP + offset, GAP * 3, funnel * (WIDTH + GAP) + WIDTH - GAP + offset, GAP);
		graphics.drawLine(funnel * (WIDTH + GAP) + WIDTH - GAP + offset, GAP, funnel * (WIDTH + GAP) + WIDTH + offset, GAP);
		
		
		final Problem currentProblem = gameModel.getProblem();
		int currentX = 10;
		
		if (gameModel.getCurrentState() == GameModel.State.MENU) {
			// Draw Menu
			final SortedMap<Integer, GameMode> options = gameModel.getGameModes();
			int displacement = GAP * 10;
			graphics.drawString("Menu:", currentX + (GAP * 10), displacement);
			for (GameMode mode : options.values()) {
				displacement += GAP * 3;
				graphics.drawString(mode.toString(), currentX + (GAP * 10), displacement);				
			}
			displacement += GAP * 3;
			graphics.drawString("Press m to toggle music.", currentX + (GAP * 10), displacement);
			
			displacement += GAP * 3;
			graphics.drawString("Press ESC to quit.", currentX + (GAP * 10), displacement);
			
			displacement += GAP * 3;
			graphics.drawString("Press SPACE to pause.", currentX + (GAP * 10), displacement);
			
			if (!gameModel.isRunning()) {
				graphics.drawString(gameOver.getIterator(), (numberOfBuckets
						* (WIDTH + GAP) + currentX) / 2, (TOTAL_HEIGHT + START_HEIGHT) / 2
						+ GAP);
			}
		} else if (!gameModel.isRunning()) {
			// Draw game over
			graphics.drawString(gameOver.getIterator(), (numberOfBuckets
					* (WIDTH + GAP) + currentX) / 2, (TOTAL_HEIGHT + START_HEIGHT) / 2
					+ GAP);
		} else if (gameModel.isPause()) {
			// Draw pause
			graphics.drawString(pause.getIterator(), (numberOfBuckets
					* (WIDTH + GAP) + currentX) / 2, (TOTAL_HEIGHT + START_HEIGHT) / 2
					+ GAP);
		} else if (currentProblem != null) {
			// Draw problem
			final int bucket = gameModel.getBucket();
			final int problemHeight = gameModel.getHeight();

			graphics.drawString(currentProblem + " = ", bucket * (WIDTH + GAP)
					+ GAP + currentX, TOTAL_HEIGHT - ((problemHeight - 1) * 20));
		}

		// Draw buckets
		graphics.clipRect(currentX, TOTAL_HEIGHT + 50, (WIDTH + GAP)
				* numberOfBuckets + 15, START_HEIGHT);
		for (Bucket bucket : buckets) {
			graphics.drawRect(currentX, TOTAL_HEIGHT, WIDTH, START_HEIGHT);

			int textY = TOTAL_HEIGHT + START_HEIGHT - GAP;
			final int textX = currentX + GAP;
			for (Problem problem : bucket.getProblems()) {
				graphics.drawString(problem.toString() + " = "
						+ problem.getAnswer(), textX, textY);
				textY -= 20;
			}
			currentX += WIDTH + GAP;
		}
		
		// Draw animation
		final Animation animation = currentAnimation;
		
		if (animation != null) {
			if (animation.isDone()) {
				currentAnimation = null;
			} else {
				graphics.setClip(null);
				animation.renderFrame(graphics);
			}
		}

	}

	public void setCurrentAnimation(Animation currentAnimation) {
		this.currentAnimation = currentAnimation;
	}

}
